home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 1 / src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1985-08-07  |  10.5 KB  |  496 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* hack.main.c - version 1.0.3 */
  3.  
  4. #include <stdio.h>
  5. #include <signal.h>
  6. #include "hack.h"
  7.  
  8. #ifdef QUEST
  9. #define    gamename    "quest"
  10. #else
  11. #define    gamename    "hack"
  12. #endif QUEST
  13.  
  14. extern char *getlogin(), *getenv();
  15. extern char plname[PL_NSIZ], pl_character[PL_CSIZ];
  16.  
  17. int (*afternmv)();
  18. int (*occupation)();
  19. char *occtxt;            /* defined when occupation != NULL */
  20.  
  21. int done1();
  22. int hangup();
  23.  
  24. int hackpid;                /* current pid */
  25. int locknum;                /* max num of players */
  26. #ifdef DEF_PAGER
  27. char *catmore;                /* default pager */
  28. #endif DEF_PAGER
  29. char SAVEF[PL_NSIZ + 11] = "save/";    /* save/99999player */
  30. char *hname;        /* name of the game (argv[0] of call) */
  31. char obuf[BUFSIZ];    /* BUFSIZ is defined in stdio.h */
  32.  
  33. extern char *nomovemsg;
  34. extern long wailmsg;
  35.  
  36. main(argc,argv)
  37. int argc;
  38. char *argv[];
  39. {
  40.     register int fd;
  41. #ifdef CHDIR
  42.     register char *dir;
  43. #endif CHDIR
  44.  
  45.     hname = argv[0];
  46.     hackpid = getpid();
  47.  
  48. #ifdef CHDIR            /* otherwise no chdir() */
  49.     /*
  50.      * See if we must change directory to the playground.
  51.      * (Perhaps hack runs suid and playground is inaccessible
  52.      *  for the player.)
  53.      * The environment variable HACKDIR is overridden by a
  54.      *  -d command line option (must be the first option given)
  55.      */
  56.  
  57.     dir = getenv("HACKDIR");
  58.     if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
  59.         argc--;
  60.         argv++;
  61.         dir = argv[0]+2;
  62.         if(*dir == '=' || *dir == ':') dir++;
  63.         if(!*dir && argc > 1) {
  64.             argc--;
  65.             argv++;
  66.             dir = argv[0];
  67.         }
  68.         if(!*dir)
  69.             error("Flag -d must be followed by a directory name.");
  70.     }
  71. #endif CHDIR
  72.  
  73.     /*
  74.      * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS
  75.      *            2. Use $USER or $LOGNAME    (if 1. fails)
  76.      *            3. Use getlogin()        (if 2. fails)
  77.      * The resulting name is overridden by command line options.
  78.      * If everything fails, or if the resulting name is some generic
  79.      * account like "games", "play", "player", "hack" then eventually
  80.      * we'll ask him.
  81.      * Note that we trust him here; it is possible to play under
  82.      * somebody else's name.
  83.      */
  84.     { register char *s;
  85.  
  86.       initoptions();
  87.       if(!*plname && (s = getenv("USER")))
  88.         (void) strncpy(plname, s, sizeof(plname)-1);
  89.       if(!*plname && (s = getenv("LOGNAME")))
  90.         (void) strncpy(plname, s, sizeof(plname)-1);
  91.       if(!*plname && (s = getlogin()))
  92.         (void) strncpy(plname, s, sizeof(plname)-1);
  93.     }
  94.  
  95.     /*
  96.      * Now we know the directory containing 'record' and
  97.      * may do a prscore().
  98.      */
  99.     if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
  100. #ifdef CHDIR
  101.         chdirx(dir,0);
  102. #endif CHDIR
  103.         prscore(argc, argv);
  104.         exit(0);
  105.     }
  106.  
  107.     /*
  108.      * It seems he really wants to play.
  109.      * Remember tty modes, to be restored on exit.
  110.      */
  111.     gettty();
  112.     setbuf(stdout,obuf);
  113.     setrandom();
  114.     startup();
  115.     cls();
  116.     u.uhp = 1;    /* prevent RIP on early quits */
  117.     u.ux = FAR;    /* prevent nscr() */
  118.     (void) signal(SIGHUP, hangup);
  119.  
  120.     /*
  121.      * Find the creation date of this game,
  122.      * so as to avoid restoring outdated savefiles.
  123.      */
  124.     gethdate(hname);
  125.  
  126.     /*
  127.      * We cannot do chdir earlier, otherwise gethdate will fail.
  128.      */
  129. #ifdef CHDIR
  130.     chdirx(dir,1);
  131. #endif CHDIR
  132.  
  133.     /*
  134.      * Process options.
  135.      */
  136.     while(argc > 1 && argv[1][0] == '-'){
  137.         argv++;
  138.         argc--;
  139.         switch(argv[0][1]){
  140. #ifdef WIZARD
  141.         case 'D':
  142. /*            if(!strcmp(getlogin(), WIZARD)) */
  143.                 wizard = TRUE;
  144. /*            else
  145.                 printf("Sorry.\n"); */
  146.             break;
  147. #endif WIZARD
  148. #ifdef NEWS
  149.         case 'n':
  150.             flags.nonews = TRUE;
  151.             break;
  152. #endif NEWS
  153.         case 'u':
  154.             if(argv[0][2])
  155.               (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
  156.             else if(argc > 1) {
  157.               argc--;
  158.               argv++;
  159.               (void) strncpy(plname, argv[0], sizeof(plname)-1);
  160.             } else
  161.                 printf("Player name expected after -u\n");
  162.             break;
  163.         default:
  164.             /* allow -T for Tourist, etc. */
  165.             (void) strncpy(pl_character, argv[0]+1,
  166.                 sizeof(pl_character)-1);
  167.  
  168.             /* printf("Unknown option: %s\n", *argv); */
  169.         }
  170.     }
  171.  
  172.     if(argc > 1)
  173.         locknum = atoi(argv[1]);
  174. #ifdef MAX_NR_OF_PLAYERS
  175.     if(!locknum || locknum > MAX_NR_OF_PLAYERS)
  176.         locknum = MAX_NR_OF_PLAYERS;
  177. #endif MAX_NR_OF_PLAYERS
  178. #ifdef DEF_PAGER
  179.     if(!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER")))
  180.         catmore = DEF_PAGER;
  181. #endif DEF_PAGER
  182. #ifdef MAIL
  183.     getmailstatus();
  184. #endif MAIL
  185. #ifdef WIZARD
  186.     if(wizard) (void) strcpy(plname, "wizard"); else
  187. #endif WIZARD
  188.     if(!*plname || !strncmp(plname, "player", 4)
  189.             || !strncmp(plname, "games", 4))
  190.         askname();
  191.     plnamesuffix();        /* strip suffix from name; calls askname() */
  192.                 /* again if suffix was whole name */
  193.                 /* accepts any suffix */
  194. #ifdef WIZARD
  195.     if(!wizard) {
  196. #endif WIZARD
  197.         /*
  198.          * check for multiple games under the same name
  199.          * (if !locknum) or check max nr of players (otherwise)
  200.          */
  201.         (void) signal(SIGQUIT,SIG_IGN);
  202.         (void) signal(SIGINT,SIG_IGN);
  203.         if(!locknum)
  204.             (void) strcpy(lock,plname);
  205.         getlock();    /* sets lock if locknum != 0 */
  206. #ifdef WIZARD
  207.     } else {
  208.         register char *sfoo;
  209.         (void) strcpy(lock,plname);
  210.         if(sfoo = getenv("MAGIC"))
  211.             while(*sfoo) {
  212.                 switch(*sfoo++) {
  213.                 case 'n': (void) srand(*sfoo++);
  214.                     break;
  215.                 }
  216.             }
  217.         if(sfoo = getenv("GENOCIDED")){
  218.             if(*sfoo == '!'){
  219.                 extern struct permonst mons[CMNUM+2];
  220.                 extern char genocided[], fut_geno[];
  221.                 register struct permonst *pm = mons;
  222.                 register char *gp = genocided;
  223.  
  224.                 while(pm < mons+CMNUM+2){
  225.                     if(!index(sfoo, pm->mlet))
  226.                         *gp++ = pm->mlet;
  227.                     pm++;
  228.                 }
  229.                 *gp = 0;
  230.             } else
  231.                 (void) strcpy(genocided, sfoo);
  232.             (void) strcpy(fut_geno, genocided);
  233.         }
  234.     }
  235. #endif WIZARD
  236.     setftty();
  237.     (void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
  238.     regularize(SAVEF+5);        /* avoid . or / in name */
  239.     if((fd = open(SAVEF,0)) >= 0 &&
  240.        (uptodate(fd) || unlink(SAVEF) == 666)) {
  241.         (void) signal(SIGINT,done1);
  242.         pline("Restoring old save file...");
  243.         (void) fflush(stdout);
  244.         if(!dorecover(fd))
  245.             goto not_recovered;
  246.         pline("Hello %s, welcome to %s!", plname, gamename);
  247.         flags.move = 0;
  248.     } else {
  249. not_recovered:
  250.         fobj = fcobj = invent = 0;
  251.         fmon = fallen_down = 0;
  252.         ftrap = 0;
  253.         fgold = 0;
  254.         flags.ident = 1;
  255.         init_objects();
  256.         u_init();
  257.  
  258.         (void) signal(SIGINT,done1);
  259.         mklev();
  260.         u.ux = xupstair;
  261.         u.uy = yupstair;
  262.         (void) inshop();
  263.         setsee();
  264.         flags.botlx = 1;
  265.         makedog();
  266.         { register struct monst *mtmp;
  267.           if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp);    /* riv05!a3 */
  268.         }
  269.         seemons();
  270. #ifdef NEWS
  271.         if(flags.nonews || !readnews())
  272.             /* after reading news we did docrt() already */
  273. #endif NEWS
  274.             docrt();
  275.  
  276.         /* give welcome message before pickup messages */
  277.         pline("Hello %s, welcome to %s!", plname, gamename);
  278.  
  279.         pickup(1);
  280.         read_engr_at(u.ux,u.uy);
  281.         flags.move = 1;
  282.     }
  283.  
  284.     flags.moonphase = phase_of_the_moon();
  285.     if(flags.moonphase == FULL_MOON) {
  286.         pline("You are lucky! Full moon tonight.");
  287.         u.uluck++;
  288.     } else if(flags.moonphase == NEW_MOON) {
  289.         pline("Be careful! New moon tonight.");
  290.     }
  291.  
  292.     initrack();
  293.  
  294.     for(;;) {
  295.         if(flags.move) {    /* actual time passed */
  296.  
  297.             settrack();
  298.  
  299.             if(moves%2 == 0 ||
  300.               (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
  301.                 extern struct monst *makemon();
  302.                 movemon();
  303.                 if(!rn2(70))
  304.                     (void) makemon((struct permonst *)0, 0, 0);
  305.             }
  306.             if(Glib) glibr();
  307.             timeout();
  308.             ++moves;
  309.             if(flags.time) flags.botl = 1;
  310.             if(u.uhp < 1) {
  311.                 pline("You die...");
  312.                 done("died");
  313.             }
  314.             if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){
  315.                 wailmsg = moves;
  316.                 if(u.uhp == 1)
  317.                 pline("You hear the wailing of the Banshee...");
  318.                 else
  319.                 pline("You hear the howling of the CwnAnnwn...");
  320.             }
  321.             if(u.uhp < u.uhpmax) {
  322.                 if(u.ulevel > 9) {
  323.                     if(Regeneration || !(moves%3)) {
  324.                         flags.botl = 1;
  325.                         u.uhp += rnd((int) u.ulevel-9);
  326.                         if(u.uhp > u.uhpmax)
  327.                         u.uhp = u.uhpmax;
  328.                     }
  329.                 } else if(Regeneration ||
  330.                     (!(moves%(22-u.ulevel*2)))) {
  331.                     flags.botl = 1;
  332.                     u.uhp++;
  333.                 }
  334.             }
  335.             if(Teleportation && !rn2(85)) tele();
  336.             if(Searching && multi >= 0) (void) dosearch();
  337.             gethungry();
  338.             invault();
  339.             amulet();
  340.         }
  341.         if(multi < 0) {
  342.             if(!++multi){
  343.                 pline(nomovemsg ? nomovemsg :
  344.                     "You can move again.");
  345.                 nomovemsg = 0;
  346.                 if(afternmv) (*afternmv)();
  347.                 afternmv = 0;
  348.             }
  349.         }
  350.  
  351.         find_ac();
  352. #ifndef QUEST
  353.         if(!flags.mv || Blind)
  354. #endif QUEST
  355.         {
  356.             seeobjs();
  357.             seemons();
  358.             nscr();
  359.         }
  360.         if(flags.botl || flags.botlx) bot();
  361.  
  362.         flags.move = 1;
  363.  
  364.         if(multi >= 0 && occupation) {
  365.             if(monster_nearby())
  366.                 stop_occupation();
  367.             else if ((*occupation)() == 0)
  368.                 occupation = 0;
  369.             continue;
  370.         }
  371.  
  372.         if(multi > 0) {
  373. #ifdef QUEST
  374.             if(flags.run >= 4) finddir();
  375. #endif QUEST
  376.             lookaround();
  377.             if(!multi) {    /* lookaround may clear multi */
  378.                 flags.move = 0;
  379.                 continue;
  380.             }
  381.             if(flags.mv) {
  382.                 if(multi < COLNO && !--multi)
  383.                     flags.mv = flags.run = 0;
  384.                 domove();
  385.             } else {
  386.                 --multi;
  387.                 rhack(save_cm);
  388.             }
  389.         } else if(multi == 0) {
  390. #ifdef MAIL
  391.             ckmailstatus();
  392. #endif MAIL
  393.             rhack((char *) 0);
  394.         }
  395.         if(multi && multi%7 == 0)
  396.             (void) fflush(stdout);
  397.     }
  398. }
  399.  
  400. glo(foo)
  401. register foo;
  402. {
  403.     /* construct the string  xlock.n  */
  404.     register char *tf;
  405.  
  406.     tf = lock;
  407.     while(*tf && *tf != '.') tf++;
  408.     (void) sprintf(tf, ".%d", foo);
  409. }
  410.  
  411. /*
  412.  * plname is filled either by an option (-u Player  or  -uPlayer) or
  413.  * explicitly (-w implies wizard) or by askname.
  414.  * It may still contain a suffix denoting pl_character.
  415.  */
  416. askname(){
  417. register int c,ct;
  418.     printf("\nWho are you? ");
  419.     (void) fflush(stdout);
  420.     ct = 0;
  421.     while((c = getchar()) != '\n'){
  422.         if(c == EOF) error("End of input\n");
  423.         /* some people get confused when their erase char is not ^H */
  424.         if(c == '\010') {
  425.             if(ct) ct--;
  426.             continue;
  427.         }
  428.         if(c != '-')
  429.         if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
  430.         if(ct < sizeof(plname)-1) plname[ct++] = c;
  431.     }
  432.     plname[ct] = 0;
  433.     if(ct == 0) askname();
  434. }
  435.  
  436. /*VARARGS1*/
  437. impossible(s,x1,x2)
  438. register char *s;
  439. {
  440.     pline(s,x1,x2);
  441.     pline("Program in disorder - perhaps you'd better Quit.");
  442. }
  443.  
  444. #ifdef CHDIR
  445. static
  446. chdirx(dir, wr)
  447. char *dir;
  448. boolean wr;
  449. {
  450.  
  451. #ifdef SECURE
  452.     if(dir                    /* User specified directory? */
  453. #ifdef HACKDIR
  454.            && strcmp(dir, HACKDIR)        /* and not the default? */
  455. #endif HACKDIR
  456.         ) {
  457.         (void) setuid(getuid());        /* Ron Wessels */
  458.         (void) setgid(getgid());
  459.     }
  460. #endif SECURE
  461.  
  462. #ifdef HACKDIR
  463.     if(dir == NULL)
  464.         dir = HACKDIR;
  465. #endif HACKDIR
  466.  
  467.     if(dir && chdir(dir) < 0) {
  468.         perror(dir);
  469.         error("Cannot chdir to %s.", dir);
  470.     }
  471.  
  472.     /* warn the player if he cannot write the record file */
  473.     /* perhaps we should also test whether . is writable */
  474.     /* unfortunately the access systemcall is worthless */
  475.     if(wr) {
  476.         register fd;
  477.  
  478.         if(dir == NULL)
  479.         dir = ".";
  480.         if((fd = open(RECORD, 2)) < 0) {
  481.         printf("Warning: cannot write %s/%s", dir, RECORD);
  482.         getret();
  483.         } else
  484.         (void) close(fd);
  485.     }
  486. }
  487. #endif CHDIR
  488.  
  489. stop_occupation()
  490. {
  491.     if(occupation) {
  492.         pline("You stop %s.", occtxt);
  493.         occupation = 0;
  494.     }
  495. }
  496.